package form

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"yunj/pkg/yunj/app/service/admin/adminservice"
	"yunj/pkg/yunj/util"

	"github.com/gin-gonic/gin"
)

type ButtonInterface interface {
	GetButtonType() (typ string, err error)                  // 获取按钮类型
	GetButtonClass() (class string, err error)               // 获取按钮class
	GetButtonId() (id string, err error)                     // 获取按钮唯一标识
	GetError() error                                         // 获取按钮错误
	HandleAttr() error                                       // 处理按钮属性
	RenderHandle(ctx *gin.Context) (hasAuth bool, err error) // 渲染处理，返回是否有权限和是否有错误
}

type Button struct {
	Type           string `json:"type"`           // 类型
	Class          string `json:"class"`          // 按钮class
	Text           string `json:"text"`           // 描述文字
	Icon           string `json:"icon"`           // 图标class
	MobileDropDown bool   `json:"mobileDropDown"` // 移动端下拉（移动端表单集成到下拉操作里）
	Auth           string `json:"auth"`           // 权限
	ErrPrefix      string `json:"-"`              // 错误前缀
	Err            error  `json:"-"`              // 错误

	// 父结构体属性
	buttonInstance ButtonInterface // 按钮实例
}

// 设置按钮实例
func SetButtonInstance(b *Button, buttonInstance ButtonInterface) {
	b.buttonInstance = buttonInstance

	// 获取指针的反射值
	buttonInstanceValue := reflect.ValueOf(b.buttonInstance)
	// 检查传入的是否为指针
	if buttonInstanceValue.Kind() != reflect.Ptr || buttonInstanceValue.IsNil() {
		b.SetError("请传入按钮实例指针值！")
	}

	// 初始化类型
	b.Type = util.LcFirst(util.TypeName(b.buttonInstance))

}

// 获取按钮类型
func (b *Button) GetButtonType() (typ string, err error) {
	err = b.GetError()
	if err != nil {
		return
	}
	typ = b.Type
	return
}

// 获取按钮class
func (b *Button) GetButtonClass() (class string, err error) {
	err = b.GetError()
	if err != nil {
		return
	}
	class = b.Class
	return
}

// 获取按钮唯一标识
func (b *Button) GetButtonId() (id string, err error) {
	err = b.GetError()
	if err != nil {
		return
	}
	var typ, class string
	typ, err = b.GetButtonType()
	if err != nil {
		return
	}
	class, err = b.GetButtonClass()
	if err != nil {
		return
	}
	id = fmt.Sprintf("%s_%s", typ, class)
	return
}

// 获取按钮实例的错误前缀
func (b *Button) getErrPrefix() (prefix string, err error) {
	err = b.GetError()
	if err != nil {
		return
	}
	prefix = b.ErrPrefix
	return
}

// 设置按钮实例的错误前缀
func (b *Button) setErrPrefix(prefix string) (err error) {
	err = b.GetError()
	if err != nil {
		return
	}
	b.ErrPrefix = prefix
	return
}

// 获取按钮错误
func (b *Button) GetError() error {
	return b.Err
}

// 设置按钮错误
func (b *Button) SetError(err any) error {
	if _err := b.GetError(); _err != nil {
		return _err
	}
	var resErrMsg string
	if _errMsg, ok := err.(string); ok {
		resErrMsg = _errMsg
	} else if _err, ok := err.(error); ok {
		resErrMsg = _err.Error()
	} else {
		resErrMsg = "未知错误！"
	}

	// 错误前缀
	errPrefix, _ := b.getErrPrefix()
	if errPrefix == "" {
		typ, _ := b.GetButtonType()
		errPrefix = fmt.Sprintf("按钮%s[%s]", typ, b.Class)
		b.setErrPrefix(errPrefix)
	}

	if !strings.HasPrefix(resErrMsg, errPrefix) {
		resErrMsg = errPrefix + resErrMsg
	}
	newErr := errors.New(resErrMsg)
	b.Err = newErr
	return newErr
}

// 处理按钮属性
func (b *Button) HandleAttr() error {
	return nil
}

// 渲染处理
// @return hasAuth: 是否有权限
// @return err: 错误消息
func (b *Button) RenderHandle(ctx *gin.Context) (hasAuth bool, err error) {
	if err = b.GetError(); err != nil {
		return
	}
	// 处理字段属性
	err = b.buttonInstance.HandleAttr()
	if err != nil {
		err = b.SetError(err)
		return
	}
	// 判断权限
	hasAuth = adminservice.CheckAuth(ctx, b.Auth)
	return
}
